﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sustainalytics.Entities;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;

namespace Sustainalytics.DataLayer.Tests
{
    [TestClass]
    public class EventsRepositoryTests
    {
        private IEventsRepository _eventsRepository { get; set; }

        [TestInitialize]
        public void Initialize()
        {
            _eventsRepository = EventsRepository.GetEventsRepository(ConfigurationManager.ConnectionStrings["ClientPlatform_Test"].ConnectionString);

            EventsTestingData.CleanupRepo(_eventsRepository);
            EventsTestingData.InitializeRepo(_eventsRepository);
        }

        [TestCleanup]
        public void Cleanup()
        {
            EventsTestingData.CleanupRepo(_eventsRepository);
        }

        [TestMethod]
        public void GetEvents_SearchText_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = Guid.NewGuid().ToString(), Sponsorship = null };
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, new[] { "Name" }, false);

            Assert.IsTrue(events != null, "result list is null.");
        }

        [TestMethod]
        public void GetEvents_Sponsorship_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = null, Sponsorship = false };
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, new[] { "Name" }, false);

            Assert.IsTrue(events != null, "result list is null.");
            Assert.AreEqual(0, events.Count);
        }

        [TestMethod]
        public void GetEvents_Sponsorship_SearchText_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = Guid.NewGuid().ToString(), Sponsorship = false };
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, new[] { "Name" }, false);

            Assert.IsTrue(events != null, "result list is null.");
            Assert.AreEqual(0, events.Count);
        }

        [TestMethod]
        public void GetEvents_IsPublished_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = null, Sponsorship = null, IsPublished = true };
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, new[] { "StartDate" }, false);

            Assert.IsTrue(events != null, "Result list is null.");
            Assert.AreEqual(10, events.Count);
            Assert.IsTrue(events.Any(x => x.Status == EventStatus.Draft) == false, "Events with status Draft were selected!");
            Assert.IsTrue(events.Any(x => x.StartDate < DateTime.UtcNow.AddMonths(-3)) == false, "Filter by StartDate not as expected!");
        }

        [TestMethod]
        public void GetEvents_IsPublished_StartDateFilter()
        {
            var filter = new EventsFilter() { SearchText = null, Sponsorship = null, IsPublished = true, StartDateBegin = DateTime.Now, StartDateEnd = DateTime.Now.AddDays(10) };
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, new[] { "StartDate" }, false);

            Assert.IsTrue(events != null, "Result list is null.");
            Assert.AreEqual(10, events.Count);
            Assert.IsTrue(events.Any(x => x.Status == EventStatus.Draft) == false, "Events with status Draft were selected!");
            Assert.IsTrue(events.Where(x => x.StartDate >= filter.StartDateBegin).Count() == 10, "Filter by StartDate not as expected!");
        }

        [TestMethod]
        public void GetEvents_EmptyFilter_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = null, Sponsorship = null };
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, new[] { "Name" }, false);

            Assert.IsTrue(events != null, "result list is null.");
            Assert.AreEqual(10, events.Count);
        }

        [TestMethod]
        public void GetEvents_NullFilter_ResultNotNull()
        {
            EventsFilter filter = null;
            List<Event> events = _eventsRepository.GetEvents(filter, 0, 10, null, false);

            Assert.IsTrue(events != null, "result list is null.");
            Assert.AreEqual(10, events.Count);
        }

        [TestMethod]
        public void GetEventsCount_SearchText_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = Guid.NewGuid().ToString(), Sponsorship = null };
            var eventsCount = _eventsRepository.GetEventsCount(filter);

            Assert.IsTrue(eventsCount == 0);
        }

        [TestMethod]
        public void GetEventsCount_Sponsorship_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = null, Sponsorship = false };
            var eventsCount = _eventsRepository.GetEventsCount(filter);

            Assert.AreEqual(0, eventsCount);
        }

        [TestMethod]
        public void GetEventsCount_Sponsorship_SearchText_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = Guid.NewGuid().ToString(), Sponsorship = false };
            var eventsCount = _eventsRepository.GetEventsCount(filter);

            Assert.AreEqual(0, eventsCount);
        }

        [TestMethod]
        public void GetEventsCount_EmptyFilter_ResultNotNull()
        {
            var filter = new EventsFilter() { SearchText = null, Sponsorship = null };
            var eventsCount = _eventsRepository.GetEventsCount(filter);

            Assert.AreEqual(30, eventsCount);
        }

        [TestMethod]
        public void GetEventsCount_NullFilter_ResultNotNull()
        {
            EventsFilter filter = null;

            var eventsCount = _eventsRepository.GetEventsCount(filter);

            Assert.AreEqual(30, eventsCount);
        }

        [TestMethod]
        public void GetEventsPaged_Filter_Term_MatchName_StartDateDesc()
        {
            string term = "UTest The Event 1";

            var filter = new EventsFilter { SearchText = term };
            List<Event> events = _eventsRepository.GetEvents(filter, 5, 10, new[] { "StartDate" }, true);

            List<Event> memEvents = EventsTestingData.EventsLst.Where(n => n.Name.ToLowerInvariant().Contains(term.ToLowerInvariant()))
                .OrderBy(n => n.StartDate)
                .Skip(5).Take(10).ToList();

            Assert.IsTrue(events != null, "Items is null");
            Assert.AreEqual(memEvents.Count, events.Count, "Items count are not equal.");
            Assert.IsTrue(events.SequenceEqual(memEvents, new EventsObjComparer()), "Items are not the same.");
        }

        [TestMethod]
        public void GetEventsPaged_Filter_Term_MatchName_StartDateAsc()
        {
            string term = "UTest The Event 1";

            var filter = new EventsFilter { SearchText = term };
            List<Event> events = _eventsRepository.GetEvents(filter, 5, 10, new[] { "StartDate" }, false);

            List<Event> memEvents = EventsTestingData.EventsLst.Where(n => n.Name.ToLowerInvariant().Contains(term.ToLowerInvariant()))
                .OrderByDescending(n => n.StartDate)
                .Skip(5).Take(10).ToList();

            Assert.IsTrue(events != null, "Items is null");
            Assert.AreEqual(memEvents.Count, events.Count, "Items count are not equal.");
            Assert.IsTrue(events.SequenceEqual(memEvents, new EventsObjComparer()), "Items are not the same.");
        }

    }
}
